\chapter{QMutexLocker}

QMutexLocker 是一个工具类，它能非常方便地将互斥量锁定以及解锁。更多内容...

\begin{tabular}{|r|l|}
	\hline
	属性 & 内容 \\
	\hline
    头文件  &	\hl{\#include<QMutexLocker>} \\
    \hline
    qmake: & QT += core    \\
	\hline
\end{tabular}

\begin{compactitem}
\item 此类中所有函数都是线程安全的。
\end{compactitem}

\section{公共成员函数}

\begin{tabular}{|r|l|}   
    \hline
    返回类型 	& 函数 \\
    \hline
    & QMutexLocker(QRecursiceMutex \emph{*mutex}) \\ 
    \hline
	&QMutexLocker(QMutex \emph{*mutex}) \\ 
    \hline
	& $\sim$QmutexLocker() \\ 
\hline
QMutex * &	mutex() const \\
\hline
void 	& relock()\\
\hline
void 	& unlock() \\ 
    \hline 
\end{tabular}


\section{详细描述}

在复杂的函数、语句或异常处理代码中锁定和解锁 QMutex 很容易出错，而且很难调试。
QMutexLocker 可用于此类情况，
以确保互斥量的状态始终定义良好。

QMutexLocker 应该在需要锁定 QMutex 的函数中创建。在创建 QMutexLocker 时互斥量被锁定。
您可以使用 unlock() 和 relock() 解锁和重新锁定互斥体。如果锁定，则当 QMutexLocker 被销毁时，互斥量将被解锁。

例如，此复杂函数在进入函数时锁定 QMutex，并在所有出口点解锁互斥量：很方便确保成对执行锁和解锁。
例如，假设有一个方法将消息打印到两行上：

\begin{cppcode}
    int complexFunction(int flag)
    {
        mutex.lock();

        int retVal = 0;

        switch (flag) {
        case 0:
        case 1:
            retVal = moreComplexFunction(flag);
            break;
        case 2:
            {
                int status = anotherFunction();
                if (status < 0) {
                    mutex.unlock();
                    return -2;
                }
                retVal = status + flag;
            }
            break;
        default:
            if (flag > 10) {
                mutex.unlock();
                return -1;
            }
            break;
        }

        mutex.unlock();
        return retVal;
    }
\end{cppcode}

该示例在开发过程中会变得更加复杂，也更加容易出错。 
使用 QMutexLocker 可大大简化代码，且可读性更好：

\begin{cppcode}
    int complexFunction(int flag)
    {
        QMutexLocker locker(&mutex);

        int retVal = 0;

        switch (flag) {
        case 0:
        case 1:
            return moreComplexFunction(flag);
        case 2:
            {
                int status = anotherFunction();
                if (status < 0)
                    return -2;
                retVal = status + flag;
            }
            break;
        default:
            if (flag > 10)
                return -1;
            break;
        }

        return retVal;
    }
\end{cppcode}

现在，当 QMutexLocker 对象被销毁时（当函数返回时，因为 locker 是一个栈变量），互斥量将始终被解锁。
同样的原则也适用于抛出和捕获异常的代码。
在将异常传递给调用函数之前，如果函数未在锁定互斥量的函数中捕获到异常，则无法解锁互斥体。

（译者注：在进入被调函数后，被调函数锁定互斥量（使用QMutex::lock()），
在执行过程中发生异常，异常被调用函数获取，被调函数就没有正确执行解锁。）

QMutexLocker 还提供一个 mutex() 成员函数，该函数返回QMutexLocker 正在其上操作的互斥体。
这对于需要访问互斥体的代码非常有用，例如 QWaitCondition::wait()。

例如:

\begin{cppcode}
    class SignalWaiter
    {
    private:
        QMutexLocker locker;

    public:
        SignalWaiter(QMutex *mutex)
            : locker(mutex)
        {
        }

        void waitForSignal()
        {
            ...
            while (!signalled)
                waitCondition.wait(locker.mutex());
            ...
        }
    };
\end{cppcode}

\begin{seeAlso}
ReadLockr，QWriteLocker，QMutex。
\end{seeAlso}

%%%%%%%%%%%%%%%%

\section{成员函数文档}

QMutexLocker::QMutexLocker(QRecursiveMutex \emph{*mutex})

构造一个 QMutexLocker 并锁定互斥量。
当 QMutexLocker 被销毁时，互斥量将被解锁（unlock()）。
如果 mutex 为空，那么 QMutexLocker 不执行任何操作。

在 Qt5.14 中引入该函数。

\begin{seeAlso}
QMutex::lock()
\end{seeAlso}

QMutexLocker::QMutexLocker(QMutex \emph{*mutex})

构造一个 并锁定互斥量。当 QMutexLocker 被销毁时，互斥量将被解锁。
如果 mutex 为空，那么 QMutexLocker 不执行任何操作。

\begin{seeAlso}
QMutex::lock()
\end{seeAlso}

QMutexLocker::$\sim$QMutexLocker()

销毁 QMutexLocker 并解除锁定构造函数中锁定的互斥量。

\begin{seeAlso}
QMutex::unlock()
\end{seeAlso}

QMutex *QMutexLocker::mutex() const

返回 QMutexLocker 正在操作的互斥量。

void QMutexLocker::relock()

重新锁定，未上锁的互斥量。

\begin{seeAlso}
unlock()
\end{seeAlso}

void QMutexLocker::unlock()

解锁这个互斥量。
您可以使用 relock() 再次锁定它。销毁时不需要锁定。

\begin{seeAlso}
relock()
\end{seeAlso}